package com.koron.rating.rating;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.koron.bean.base.Response;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.FastJsonUtils;
import com.koron.common.core.util.OrgCacheUtils;
import com.koron.common.core.util.StringUtils;
import com.koron.rating.classify.bean.RatingUnitBean;
import com.koron.rating.classify.mapper.RatingUnitMapper;
import com.koron.rating.enums.UnitCensusTypeEnum;
import com.koron.rating.enums.UnitTypeEnum;
import com.koron.rating.enums.UnitTypeReportEnum;
import com.koron.rating.feign.DefectCountFeign;
import com.koron.rating.feign.SpecialCountFeign;
import com.koron.rating.feign.bean.DefectEquipmentDto;
import com.koron.rating.feign.bean.DefectEquipmentQuery;
import com.koron.rating.feign.bean.SpProjectDeviceQuery;
import com.koron.rating.rating.bean.*;
import com.koron.rating.rating.mapper.RatingCompanyMapper;
import com.koron.rating.rating.mapper.RatingOrderMapper;
import com.koron.rating.rating.mapper.RatingUnitHistoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: rocky
 * @Date: 2022/1/11 9:49
 */
@Service
@Slf4j
public class RatingService {

    @Autowired
    private OrgCacheUtils orgCacheUtils;

    @Autowired
    DefectCountFeign deviceservice;

    @Autowired
    SpecialCountFeign SpecialCountFeign;

    @TaskAnnotation("synUnit")
    public void newSynUnit(SessionFactory factory, String orderId) {

        RatingOrderMapper ordermapper = factory.getMapper(RatingOrderMapper.class);
        RatingUnitMapper unitMapper = factory.getMapper(RatingUnitMapper.class);
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);

        // 部门id
        RatingOrderBean ratingOrderBean = ordermapper.selectByPrimaryKey(orderId);
        String deptId = ratingOrderBean.getDeptId();
        List<RatingUnitBean> ratingUnitBeanList = unitMapper.queryByDeptIdAndRatingIdIsNull(deptId);
        Map<String, String> isratingmap = CodeTools.getDictByClassCode("equipmentRating", "is_sql_rating");
        if ("是".equals(isratingmap.get("is_rating"))) {
            Assert.isFalse(CollUtil.isNotEmpty(ratingUnitBeanList), StrUtil.format("请维护 {} 评级标准", ratingOrderBean.getDeptName()));
        }

        /**
         *最新单元划分 单元自身的id 会 覆盖 自身的data_sources字段，保持两边的data_sources 一致
         * 对不一致的进行 更新或删除
         */
        List<RatingUnitHistoryBean> beforGradelist = Opt.ofNullable(unitMapper.queryBeforGrade()).orElse(new ArrayList<>());
        Map<String, Date> beforratingtimemap = new HashMap<>(); //上次设备评级时间
        Map<String, Integer> beforgrademap = new HashMap<>();   //上次设备评级结果
        for (RatingUnitHistoryBean befor : beforGradelist) {
            beforratingtimemap.put(befor.getId(), befor.getCreateTime());
            beforgrademap.put(befor.getId(), befor.getNowGrade());
        }

        if (mapper.countByOrderId(orderId) == 0) {
            List<RatingUnitBean> newestlist = unitMapper.queryAllByrRating();
            ArrayList<RatingUnitHistoryBean> list = new ArrayList<>();
            for (RatingUnitBean bean : newestlist) {
                RatingUnitHistoryBean hisbean = Convert.convert(RatingUnitHistoryBean.class, bean);
                hisbean.setDataSources(bean.getId());       //先吧原有单元划分id 赋值给 源id
                hisbean.setId(CodeTools.getCode32());
                hisbean.setOrderId(orderId);                //评级单id
                hisbean.setBeforRatingTime(beforratingtimemap.get(bean.getId()));   //上次评级完成时间
                hisbean.setBeforGrade(beforgrademap.get(bean.getId()));             //上衣评级结果
                hisbean.setCreateTime(new Date());
                list.add(hisbean);
            }
            List<List<RatingUnitHistoryBean>> partition = Lists.partition(list, 300);//每300条调一次库
            partition.stream().forEach(p -> {
                mapper.batchInsert(p);
            });

        } else {

            //  找到评级单元修改的记录
            List<String> deptIds = getDeptId(factory, orderId);

            List<String> equipmentIds = unitMapper.selectByDeptId(deptIds);

            List<String> unitIds = unitMapper.selectByEquipmentIds(equipmentIds);

            // 找到当前评级单
            List<String> unitHistoryDatasource = mapper.selectByOrderId(orderId);

            // 新增了设备
            if (unitIds.size() > unitHistoryDatasource.size()){
                List<String> insertIds = CollUtil.subtractToList(unitIds, unitHistoryDatasource);

                // 找到设备评级划分信息
                List<RatingUnitBean> ratingUnitBeans = unitMapper.queryRatingByIds(insertIds);

                ArrayList<RatingUnitHistoryBean> list = new ArrayList<>();
                for (RatingUnitBean bean : ratingUnitBeans) {
                    RatingUnitHistoryBean unitHistoryBean = Convert.convert(RatingUnitHistoryBean.class, bean);
                    unitHistoryBean.setDataSources(bean.getId());       //先吧原有单元划分id 赋值给 源id
                    unitHistoryBean.setId(CodeTools.getCode32());
                    unitHistoryBean.setOrderId(orderId);                //评级单id
                    unitHistoryBean.setBeforRatingTime(beforratingtimemap.get(bean.getId()));   //上次评级完成时间
                    unitHistoryBean.setBeforGrade(beforgrademap.get(bean.getId()));             //上衣评级结果
                    unitHistoryBean.setCreateTime(new Date());
                    list.add(unitHistoryBean);
                }
                List<List<RatingUnitHistoryBean>> partition = Lists.partition(list, 300);//每300条调一次库
                partition.stream().forEach(p -> {
                    mapper.batchInsert(p);
                });

            }else {
                // 删除了设备
                List<String> deleteIds = CollUtil.subtractToList(unitHistoryDatasource, unitIds);
                if (CollUtil.isNotEmpty(deleteIds)){
                    mapper.deleteInId(orderId, deleteIds);
                }
            }
        }
        return;
    }

    @Deprecated
    //@TaskAnnotation("synUnit")
    public void synUnit(SessionFactory factory, String orderId) {

        RatingOrderMapper ordermapper = factory.getMapper(RatingOrderMapper.class);
        RatingUnitMapper unitMapper = factory.getMapper(RatingUnitMapper.class);
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);

        // 部门id
        RatingOrderBean ratingOrderBean = ordermapper.selectByPrimaryKey(orderId);
        String deptId = ratingOrderBean.getDeptId();
        List<RatingUnitBean> ratingUnitBeanList = unitMapper.queryByDeptIdAndRatingIdIsNull(deptId);
        Map<String, String> isratingmap = CodeTools.getDictByClassCode("equipmentRating", "is_sql_rating");
        if ("是".equals(isratingmap.get("is_rating"))) {
            Assert.isFalse(CollUtil.isNotEmpty(ratingUnitBeanList), StrUtil.format("请维护 {} 评级标准", ratingOrderBean.getDeptName()));
        }

        /**
         *最新单元划分 单元自身的id 会 覆盖 自身的data_sources字段，保持两边的data_sources 一致
         * 对不一致的进行 更新或删除
         */
        List<RatingUnitBean> newestlist = unitMapper.queryAllByrRating();
        List<RatingUnitHistoryBean> beforGradelist = Opt.ofNullable(unitMapper.queryBeforGrade()).orElse(new ArrayList<>());
        Map<String, Date> beforratingtimemap = new HashMap<>(); //上次设备评级时间
        Map<String, Integer> beforgrademap = new HashMap<>();   //上次设备评级结果
        for (RatingUnitHistoryBean befor : beforGradelist) {
            beforratingtimemap.put(befor.getId(), befor.getCreateTime());
            beforgrademap.put(befor.getId(), befor.getNowGrade());
        }

        if (mapper.countByOrderId(orderId) == 0) {
            ArrayList<RatingUnitHistoryBean> list = new ArrayList<>();
            for (RatingUnitBean bean : newestlist) {
                RatingUnitHistoryBean hisbean = Convert.convert(RatingUnitHistoryBean.class, bean);
                hisbean.setDataSources(bean.getId());       //先吧原有单元划分id 赋值给 源id
                hisbean.setId(CodeTools.getCode32());
                hisbean.setOrderId(orderId);                //评级单id
                hisbean.setBeforRatingTime(beforratingtimemap.get(bean.getId()));   //上次评级完成时间
                hisbean.setBeforGrade(beforgrademap.get(bean.getId()));             //上衣评级结果
                hisbean.setCreateTime(new Date());
                list.add(hisbean);
            }
            List<List<RatingUnitHistoryBean>> partition = Lists.partition(list, 300);//每300条调一次库
            partition.stream().forEach(p -> {
                mapper.batchInsert(p);
            });

        } else {
            List<String> newestids = newestlist.stream().map(RatingUnitBean::getId).collect(Collectors.toList());//所有单元划分的id

            List<RatingUnitBean> oldlist = mapper.queryAllByOrderId(orderId);//对应评级单对应的单元划分记录
            // 本次评级结果
            List<RatingUnitHistoryBean> nowGradelist = mapper.queryByOrderId(orderId);
            Map<String, RatingUnitHistoryBean> nowGrademap = nowGradelist.stream().collect(Collectors.toMap(RatingUnitHistoryBean::getDataSources, item -> item));
            List<String> oldids = oldlist.stream().map(RatingUnitBean::getDataSources).collect(Collectors.toList());

            List<String> insertids = CollUtil.subtractToList(newestids, oldids);//找评级单没有的单元划分id    计算集合的单差集，即只返回【集合1】中有，但是【集合2】中没有的元素
            if (StringUtils.isNotEmpty(insertids)) {
                List<RatingUnitHistoryBean> insertlist = BatchConvertAndOptionDB(mapper, newestlist, insertids, orderId, beforratingtimemap, beforgrademap, null);
                Lists.partition(insertlist, 300).stream().forEach(p -> {
                    mapper.batchInsert(p);
                });
            }

            //            Collection<RatingUnitBean> noupdate = CollUtil.intersection(newestlist, oldlist);//找初完全一致的数据
            List<RatingUnitBean> noupdate = new ArrayList<>();
            for (RatingUnitBean bean : newestlist) {
                for (RatingUnitBean oldbean : oldlist) {
                    if (bean.equals(oldbean)) {
                        noupdate.add(bean);
                    }
                }
            }
            List<String> noupdateID = noupdate.stream().map(RatingUnitBean::getId).collect(Collectors.toList());
            oldids.removeAll(noupdateID);//去掉不需要操作的记录

            List<String> deleteIds = CollUtil.subtractToList(oldids, newestids);//找评级单对多余的id    计算集合的单差集，即只返回【集合1】中有，但是【集合2】中没有的元素
            if (CollUtil.isNotEmpty(deleteIds)) {
                mapper.deleteInId(orderId, oldids);
            }

            oldids.removeAll(deleteIds);//再去掉删除的记录，剩下的就是需要更新id

            if (CollUtil.isNotEmpty(oldids)) {
                List<RatingUnitHistoryBean> updatelist = BatchConvertAndOptionDB(mapper, newestlist, oldids, orderId, beforratingtimemap, beforgrademap, nowGrademap);
                Lists.partition(updatelist, 300).stream().forEach(p -> {
                    mapper.updateBatchSelective(orderId, p);
                });
            }
        }
        return;
    }


    /**
     * 批量类型转成 RatingUnitHistoryBean 且 写库
     *
     * @param mapper
     * @param newestlist         所有单元划分记录
     * @param dyids              单元划分id\需要更新的id
     * @param orderId            单元划分id
     * @param beforratingtimemap 上次评级完成时间
     * @param beforgrademap      上次评级结果
     * @param nowGrademap        本次评级结果     发生场景，已经评级后，驳回修改单元划分，重新点击同步按钮，保留原有评级结果
     */
    private List<RatingUnitHistoryBean> BatchConvertAndOptionDB(RatingUnitHistoryMapper mapper,
                                                                List<RatingUnitBean> newestlist,
                                                                List<String> dyids, String orderId,
                                                                Map<String, Date> beforratingtimemap,
                                                                Map<String, Integer> beforgrademap,
                                                                Map<String, RatingUnitHistoryBean> nowGrademap) {

        List<RatingUnitHistoryBean> list = newestlist.stream()
                .filter(n -> dyids.contains(n.getId()))//匹配出更新数据
                .map(new Function<RatingUnitBean, RatingUnitHistoryBean>() {
                    @Override
                    public RatingUnitHistoryBean apply(RatingUnitBean ratingUnitBean) {
                        RatingUnitHistoryBean convert = Convert.convert(RatingUnitHistoryBean.class, ratingUnitBean);
                        convert.setDataSources(ratingUnitBean.getId());
                        convert.setId(CodeTools.getCode32());
                        convert.setOrderId(orderId);
                        convert.setBeforRatingTime(beforratingtimemap.get(ratingUnitBean.getId()));   //上次评级完成时间
                        convert.setBeforGrade(beforgrademap.get(ratingUnitBean.getId()));             //上衣评级结果
                        if (MapUtil.isNotEmpty(nowGrademap)) {
                            RatingUnitHistoryBean nowGradebean = nowGrademap.get(convert.getDataSources());
                            convert.setNowGrade(nowGradebean.getNowGrade());           //重新同步原有的评级结果
                            convert.setGradeRemarks(nowGradebean.getGradeRemarks());   //重新同步原有的评级备注
                        }
                        return convert;
                    }
                })
                .collect(Collectors.toList());
        return list;
    }


    // ===================================================================================================================
    // 单元树

    @TaskAnnotation("getInitTreeLazy")
    public Response getInitTreeLazy(SessionFactory factory, String orderId) {
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        List<String> detptlist = getDeptId(factory, orderId);//获取评级单相应的评级单位Id

        Assert.isFalse(StringUtils.isEmpty(detptlist), "对应评级单位还没有单元划分");

        List<RatingUnitHistoryBean> list = mapper.queryByOrderIdAndInDeptId(orderId, detptlist);//根据评级单id 和 评级单位id
        list.stream().forEach(equipment -> equipment.setChildrenNum(mapper.countChildren(orderId, equipment.getDataSources())));//根据源id
        return Response.succ(list);
    }

    @TaskAnnotation("getTreeLazy")
    public Response getTreeLazy(SessionFactory factory, String orderId, String parentId) {
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        List<RatingUnitHistoryBean> list = mapper.list(orderId, null, parentId, null);
        String berforOrderId = getberforOrderId(orderId);
        Map<String, Integer> berforRatingGrademap = new HashMap<>();
        // 上次评级时间
        Date beforRatingTime = null;
        if (StrUtil.isNotBlank(berforOrderId)) {
            RatingOrderBean ratingOrderBean = factory.getMapper(RatingOrderMapper.class).selectByPrimaryKey(orderId);
            beforRatingTime = ratingOrderBean.getRatingTime();
            // 所有上次评级设备部件等级map
            berforRatingGrademap = getBerforRatingGrade(mapper, berforOrderId);
        }
        for (RatingUnitHistoryBean equipment : list) {
            if (MapUtil.isNotEmpty(berforRatingGrademap)) {
                equipment.setBeforGrade(berforRatingGrademap.get(equipment.getEquipmentId()));
            }
            equipment.setChildrenNum(mapper.countChildren(orderId, equipment.getId()));
            equipment.setBeforRatingTime(beforRatingTime);
        }
        return Response.succ(list);
    }


    /**
     * 树 模糊 只查 部门、单位
     *
     * @param factory
     * @param orderId
     * @param name
     * @return
     */
    @TaskAnnotation("searchByNameOntree")
    public Response<List<RatingUnitHistoryBean>> searchByNameOntree(SessionFactory factory, String orderId, String name) {
        if (StringUtils.isEmpty(name)) {
            return Response.succ(Collections.emptyList());
        }
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        String deptId = factory.getMapper(RatingOrderMapper.class).selectByPrimaryKey(orderId).getDeptId();
        //        List<String> detptlist = getDeptId(factory, orderId);//获取评级单相应的评级单位Id
        List<RatingUnitHistoryBean> result = mapper.list(orderId, deptId, null, name);//评级单id 、单元名称 模糊查询
        return Response.succ(result);
    }

    /**
     * 设备、部件 查询
     *
     * @param factory
     * @param dto
     * @return
     */
    @TaskAnnotation("searchByNameOnRating")
    public Response<List<RatingUnitHistoryVo>> searchByNameOnRating(SessionFactory factory, RatingUnitHistoryDto dto) {
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        // 上次评级单id
        String berforOrderId = getberforOrderId(dto.getOrderId());
        // 设备部件上次评级的等级
        Map<String, Integer> berforRatingmap = getBerforRatingGrade(mapper, berforOrderId);

        // 上次评级时间
        Date beforRatingTime = Opt.ofNullable(factory.getMapper(RatingOrderMapper.class).selectByPrimaryKey(berforOrderId)).map(RatingOrderBean::getRatingTime).orElse(null);

        //设备级 找 部件级
        if (StringUtils.isEmpty(dto.getUnitType()) || dto.getUnitType().equals(UnitTypeEnum.LEVEL5.getValue())) {
            List<RatingUnitHistoryVo> sblist = mapper.queryByAll(dto);
            if (StringUtils.isEmpty(sblist)) {
                return Response.succ(new ArrayList<>());
            }
            List<String> dataSources = sblist.stream().map(RatingUnitHistoryVo::getDataSources).collect(Collectors.toList());//设备级的 源id
            List<RatingUnitHistoryVo> bjlist = mapper.queryByParentIdAndOrderIdAndUnitType(dataSources, dto.getOrderId(), dto.getDeptId(), UnitTypeEnum.LEVEL6.getValue());

            Map<String, Integer> defect = queryFectCount(sblist, bjlist, beforRatingTime);//查缺陷数量
            Map<String, Integer> special = querySpecialCount(sblist, bjlist, beforRatingTime);//查专项数量

            matching(sblist, bjlist, defect, special, berforRatingmap, beforRatingTime);

            // 统计设备级和单元级
            long equipments = Optional.ofNullable(sblist.stream().count()).orElse(0L);
            long parts = Optional.ofNullable(sblist.stream()
                    .flatMap(s -> s.getDet() != null ? s.getDet().stream() : Stream.empty())
                    .count())
                    .orElse(0L);
            //            matching(sblist, bjlist, new HashMap<>(), new HashMap<>(), berforRatingmap, beforRatingTime);
            return Response.success(equipments + "," + parts,sblist);
        }
        //部件级 反向找 设备级
        if (dto.getUnitType().equals(UnitTypeEnum.LEVEL6.getValue())) {
            List<String> sbids = mapper.queryDataSourcesByOrderIdAndParentId(dto.getOrderId(), dto.getParentId());//单元级下所有设备的id
            dto.setParentId(null);
            List<RatingUnitHistoryVo> bjlist = mapper.queryByAll(dto);//可能包括了其他单元的的部件
            if (StringUtils.isEmpty(bjlist)) {
                return Response.succ(new ArrayList<>());
            }
            //            List<String> parentIds = bjlist.stream().map(RatingUnitHistoryVo::getParentId).collect(Collectors.toList());//部件的 父级id
            //            parentIds.removeIf(p -> !sbids.contains(p));//去掉其他单元的设备id
            bjlist = bjlist.stream().filter(b -> sbids.contains(b.getParentId())).collect(Collectors.toList());
            List<String> parentIds = bjlist.stream().map(RatingUnitHistoryVo::getParentId).collect(Collectors.toList());
            List<RatingUnitHistoryVo> sblist = mapper.queryByDataSourcesAndOrderIdAndUnitType(parentIds, dto.getOrderId(), dto.getDeptId(), UnitTypeEnum.LEVEL5.getValue());

            Map<String, Integer> defect = queryFectCount(sblist, bjlist, beforRatingTime);//查缺陷数量
            Map<String, Integer> special = querySpecialCount(sblist, bjlist, beforRatingTime);//查专项数量

            matching(sblist, bjlist, defect, special, berforRatingmap, beforRatingTime);

            // 统计设备级和单元级
            long equipments = Optional.ofNullable(sblist.stream().count()).orElse(0L);
            long parts = Optional.ofNullable(sblist.stream()
                    .flatMap(s -> s.getDet() != null ? s.getDet().stream() : Stream.empty())
                    .count())
                    .orElse(0L);

            //            matching(sblist, bjlist, new HashMap<>(), new HashMap<>(), berforRatingmap, beforRatingTime);
            return Response.success(equipments + "," + parts,sblist);
        }
        return Response.succ(new ArrayList<>());
    }

    /**
     * 设备部件上次评级的等级
     *
     * @param mapper
     * @param berforOrderId 上次评级单id
     * @return
     */
    private Map<String, Integer> getBerforRatingGrade(RatingUnitHistoryMapper mapper, String berforOrderId) {
        // 上次评级所有节点
        List<RatingUnitHistoryBean> berforRatingNode = mapper.queryByOrderIdAndUnitTypeIn(berforOrderId, CollUtil.newArrayList("4", "5", "6"));
        // 上次评级等级
        Map<String, Integer> berforRatingmap = new HashMap<>();
        if (CollUtil.isNotEmpty(berforRatingNode)) {
            berforRatingmap = berforRatingNode.stream().collect(Collectors.toMap(
                    new Function<RatingUnitHistoryBean, String>() {
                        @Override
                        public String apply(RatingUnitHistoryBean berfor) {
                            return berfor.getEquipmentId();
                        }
                    },
                    new Function<RatingUnitHistoryBean, Integer>() {
                        @Override
                        public Integer apply(RatingUnitHistoryBean berfor) {
                            if (berfor.getNowGrade() == null) {
                                return 0;
                            }
                            return berfor.getNowGrade();
                        }
                    }));
        }
        return berforRatingmap;
    }

    /**
     * 查询设备缺陷数量
     *
     * @param sblist          设备数据
     * @param bjlist          部件数据
     * @param beforRatingTime 上次评级时间
     */
    private Map<String, Integer> queryFectCount(List<RatingUnitHistoryVo> sblist, List<RatingUnitHistoryVo> bjlist, Date beforRatingTime) {
        Map<String, Integer> defect = new HashMap<>();
        List<RatingUnitHistoryVo> tem = CollUtil.unionAll(sblist, bjlist);//设备、部件结合
        List<DefectEquipmentQuery> defectlist = tem.stream().map(new Function<RatingUnitHistoryVo, DefectEquipmentQuery>() {
            @Override
            public DefectEquipmentQuery apply(RatingUnitHistoryVo historyVo) {
                return new DefectEquipmentQuery(historyVo.getEquipmentId(), beforRatingTime, new Date());
            }
        }).collect(Collectors.toList());
        Response response = deviceservice.queryEquipmentDefectNums(defectlist);
        Assert.isFalse(response.getCode() != 200, response.getDescription());

        if (response.getCode() == 200) {
            String beanToJson = FastJsonUtils.getBeanToJson(response.getData());
            log.info(StrUtil.format("远程调用台账数据：{}", beanToJson));
            List<DefectEquipmentDto> jsonToList = FastJsonUtils.getJsonToList(beanToJson, DefectEquipmentDto.class);
            if (StringUtils.isNotEmpty(jsonToList)) {
                defect = jsonToList.stream().collect(Collectors.toMap(DefectEquipmentDto::getEquipmentId, DefectEquipmentDto::getNum));
            }
        }

        return defect;
    }

    /**
     * 查询设备专项数量
     *
     * @param sblist          设备数据
     * @param bjlist          部件数据
     * @param beforRatingTime 上次评级时间
     */
    private Map<String, Integer> querySpecialCount(List<RatingUnitHistoryVo> sblist, List<RatingUnitHistoryVo> bjlist, Date beforRatingTime) {
        Map<String, Integer> special = new HashMap<>();
        List<RatingUnitHistoryVo> tem = CollUtil.unionAll(sblist, bjlist);//设备、部件结合
        List<SpProjectDeviceQuery> defectlist = tem.stream().map(new Function<RatingUnitHistoryVo, SpProjectDeviceQuery>() {
            @Override
            public SpProjectDeviceQuery apply(RatingUnitHistoryVo historyVo) {
                return new SpProjectDeviceQuery(historyVo.getEquipmentId(), beforRatingTime, new Date());
            }
        }).collect(Collectors.toList());
        Response response = SpecialCountFeign.countByDeviceIds(defectlist);
        Assert.isFalse(response.getCode() != 200, response.getDescription());

        if (response.getCode() == 200) {
            String beanToJson = FastJsonUtils.getBeanToJson(response.getData());
            log.info(StrUtil.format("远程调用台账数据：{}", beanToJson));
            List<SpProjectDeviceQuery> jsonToList = FastJsonUtils.getJsonToList(beanToJson, SpProjectDeviceQuery.class);
            if (StringUtils.isNotEmpty(jsonToList)) {
                special = jsonToList.stream().collect(Collectors.toMap(SpProjectDeviceQuery::getEquipmentId, SpProjectDeviceQuery::getNum));
            }
        }

        return special;
    }

    /**
     * 1、赋值缺陷数量
     * 设备匹配部件
     * 有部件一定有设备
     * 有设备不一定有部件
     * 2、赋值上次评级结果
     *
     * @param sblist          设备级
     * @param bjlist          部件级
     * @param berforRatingmap 上次评级的结果
     */
    private void matching(List<RatingUnitHistoryVo> sblist, List<RatingUnitHistoryVo> bjlist, Map<String, Integer> defect, Map<String, Integer> special, Map<String, Integer> berforRatingmap, Date beforRatingTime) {
        if (StringUtils.isEmpty(sblist)) {
            return;
        }
        sblist.stream().forEach(sb -> {
            sb.setDefectCount(defect.get(sb.getEquipmentId()));//设备 缺陷数量 赋值
            sb.setSpecialCount(special.get(sb.getEquipmentId()));//设备 专项数量 赋值
            sb.setBeforGrade(berforRatingmap.get(sb.getEquipmentId()));//设备上次评级结果
            sb.setBeforRatingTime(beforRatingTime);
            if (StringUtils.isNotEmpty(bjlist)) {
                //                j.setDefectCount(defect.get(j.getEquipmentId()));//部件 缺陷数量 赋值
                sb.setDet(bjlist.stream()
                        .filter(bj -> bj.getParentId().equals(sb.getDataSources()))     //设备级 匹配 部件级
                        .map(historyVo -> {
                            historyVo.setDefectCount(defect.get(historyVo.getEquipmentId()));
                            historyVo.setSpecialCount(special.get(historyVo.getEquipmentId()));
                            historyVo.setBeforGrade(berforRatingmap.get(historyVo.getEquipmentId()));//部件上次评级结果
                            historyVo.setBeforRatingTime(beforRatingTime);
                            return historyVo;
                        })
                        .collect(Collectors.toList()));

            }
        });
    }

    @TaskAnnotation("getParentIds")
    public Response<List<String>> getParentIds(SessionFactory factory, String orderId, String dataSources) {
        List<String> list = new LinkedList<>();
        RatingUnitHistoryBean equipment = getByDataSources(factory, orderId, dataSources).getData();
        while (!StringUtils.equals(equipment.getParentId(), "0")) {
            equipment = getByDataSources(factory, orderId, equipment.getParentId()).getData();
            list.add(0, equipment.getId());
        }
        return Response.succ(list);
    }

    @TaskAnnotation("getByDataSources")
    public Response<RatingUnitHistoryBean> getByDataSources(SessionFactory factory, String orderId, String dataSources) {
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        RatingUnitHistoryBean ratingunit = mapper.queryByOrderIdAndDataSources(orderId, dataSources);
        Assert.notNull(ratingunit, "单元不存在");
        ratingunit.setDeptName(orgCacheUtils.getOrgNameById(ratingunit.getDeptId()));
        return Response.success(ratingunit);
    }

    /**
     * 获取评级单相应的评级单位Id
     *
     * @param factory
     * @param orderId 评级单id
     * @return
     */
    private List<String> getDeptId(SessionFactory factory, String orderId) {
        RatingCompanyMapper companymapper = factory.getMapper(RatingCompanyMapper.class);
        return companymapper.queryByOrderId(orderId).stream().map(RatingCompanyBean::getCompanyId).collect(Collectors.toList());
    }


    //单元树
    // ===================================================================================================================


    /**
     * 本年评级分布 饼图
     *
     * @param factory
     * @param orderId 评级单id
     * @return
     */
    @TaskAnnotation("getThisOrderPic")
    public List<RatingGroupCountVo> getThisOrderPic(SessionFactory factory, String orderId, String type) {
        RatingUnitHistoryMapper companymapper = factory.getMapper(RatingUnitHistoryMapper.class);
        RatingOrderMapper ordermapper = factory.getMapper(RatingOrderMapper.class);

        //本次评级分布 饼图
        if (type.equals(UnitCensusTypeEnum.NOW.getLabel())) {
            return getRatingGroupCountVos(factory, orderId, companymapper);
        }

        //上次评级分布 饼图
        if (type.equals(UnitCensusTypeEnum.BEFOR.getLabel())) {
            RatingOrderBean thisrOrder = ordermapper.selectByPrimaryKey(orderId);//本次评级单信息
            //            List<RatingOrderBean> beforRating = ordermapper.queryByRatingTimeBefore(thisrOrder.getCreateTime(), thisrOrder.getDeptId(), orderId);
            //            if (StringUtils.isEmpty(beforRating)) {
            //                return new ArrayList<>();
            //            }
            //            String beforOderId = beforRating.get(beforRating.size() - 1).getId();//获取相应部门上次的评级单id
            String berforOrderId = getberforOrderId(thisrOrder.getId());
            return getRatingGroupCountVos(factory, berforOrderId, companymapper);
        }
        return new ArrayList<>();
    }

    /**
     * 统计分类登记个数
     *
     * @param orderId
     * @param companymapper
     * @return
     */
    private List<RatingGroupCountVo> getRatingGroupCountVos(SessionFactory factory, String orderId, RatingUnitHistoryMapper companymapper) {
        Integer nowTotallQty = companymapper.countByOrderIdGroupCount(orderId);//评级所有需要评级的数量
        if (nowTotallQty == 0) {
            return new ArrayList<>();
        }
        List<RatingCompanyBean> ratingCompanyBeans = factory.getMapper(RatingCompanyMapper.class).queryByOrderId(orderId);
        List<String> deptId = ratingCompanyBeans.stream().map(RatingCompanyBean::getCompanyId).collect(Collectors.toList());
        List<RatingUnitBean> unitlist = factory.getMapper(RatingUnitMapper.class).queryByEquipmentIdIn(deptId);
        List<String> eqIdlist = unitlist.stream().map(RatingUnitBean::getId).collect(Collectors.toList());
        List<RatingGroupCountVo> ratingGroupCountVos = companymapper.queryNowGradeByOrderIdAndUnitTypeIn(orderId, eqIdlist);
        ratingGroupCountVos.stream().forEach(r -> {
            r.setRatio(r.getSubtotal().divide(BigDecimal.valueOf(nowTotallQty), 2, BigDecimal.ROUND_HALF_UP));//计算百分比
        });
        return ratingGroupCountVos;
    }


    /**
     * 评级情况汇总表
     *
     * @param factory
     * @param dto     评级单id
     * @return
     */
    @TaskAnnotation("compareReport")
    public List<RatringComparisonVo> compareReport(SessionFactory factory, RatringComparisonDto dto) {
        List<RatringComparisonVo> result = new ArrayList<>();

        String orderId = dto.getOrderId();//评级单id
        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        List<RatingUnitHistoryBean> ratingUnitHistorylist = mapper.queryByOrderId(orderId);//评级单所有评级记录
        // 所有节点，用于过滤 评级单，有评级单位，没有该单位的设备历史的部门
        List<String> eqidlist = ratingUnitHistorylist.stream().map(RatingUnitHistoryBean::getEquipmentId).collect(Collectors.toList());


        if (StringUtils.isBlank(orderId)) {
            //这是本年的的评级单位 （也就是自身评级单）， 上年的要与本年的评级单位一致
            for (RatingCompanyBean company : dto.getDet()) {
                RatringComparisonVo zucompany = new RatringComparisonVo(company.getCompanyId(), company.getCompanyName(), true);//主要设备
                RatringComparisonVo cicompany = new RatringComparisonVo(company.getCompanyId(), company.getCompanyName(), false);//次要设备
                result.add(zucompany);
                result.add(cicompany);
            }
            result.add(new RatringComparisonVo("", "总计", true));
            result.add(new RatringComparisonVo("", "总计", false));
            return result;
        }

        //这是本年的的评级单位 （也就是自身评级单）， 上年的要与本年的评级单位一致
        //遍历单位（本年与上年的 单位 都要去本单据的）
        List<RatingCompanyBean> comBeans = dto.getDet().stream().map(com -> {
            RatingCompanyBean ratingCompanyBean = new RatingCompanyBean();
            ratingCompanyBean.setCompanyId(com.getCompanyId());
            ratingCompanyBean.setCompanyName(com.getCompanyName());
            return ratingCompanyBean;
        }).distinct().collect(Collectors.toList());
        for (RatingCompanyBean company : comBeans) {
            if (!eqidlist.contains(company.getCompanyId())) {
                continue;
            }
            RatringComparisonVo zucompany = new RatringComparisonVo(company.getCompanyId(), company.getCompanyName(), true);//主要设备
            RatringComparisonVo cicompany = new RatringComparisonVo(company.getCompanyId(), company.getCompanyName(), false);//次要设备
            String dataSources = mapper.queryByOrderIdAndEquipmentId(orderId, company.getCompanyId()).stream().findFirst().get().getDataSources();//找出单位 对应的 data_sources
            List<RatringReportDo> zhureportdos = mapper.queryByOrderIdAndIscoreAndFullPathCodeLike(orderId, true, dataSources);//找出主要设备各分类的统计数量
            List<RatringReportDo> cireportdos = mapper.queryByOrderIdAndIscoreAndFullPathCodeLike(orderId, false, dataSources);//找出次要设备各分类的统计数量

            //主要 分类 统计数量
            RatringReportDo one = zhureportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLASSONE.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo two = zhureportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLASSTWO.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo three = zhureportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLASSTHREE.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo four = zhureportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLSSFOUR.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo wait = zhureportdos.stream().filter(zh -> zh.getNowGrade() == null).findFirst().orElse(new RatringReportDo());
            zucompany.setOne(one.getQty());
            zucompany.setTwo(two.getQty());
            zucompany.setThree(three.getQty());
            zucompany.setFour(four.getQty());
            zucompany.setWait(wait.getQty());

            //次要 分类 统计数量
            RatringReportDo cione = cireportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLASSONE.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo citwo = cireportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLASSTWO.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo cithree = cireportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLASSTHREE.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo cifour = cireportdos.stream().filter(zh -> zh.getNowGrade() != null && zh.getNowGrade().compareTo(UnitTypeReportEnum.CLSSFOUR.getValue()) == 0).findFirst().orElse(new RatringReportDo());
            RatringReportDo ciwait = cireportdos.stream().filter(zh -> zh.getNowGrade() == null).findFirst().orElse(new RatringReportDo());
            cicompany.setOne(cione.getQty());
            cicompany.setTwo(citwo.getQty());
            cicompany.setThree(cithree.getQty());
            cicompany.setFour(cifour.getQty());
            cicompany.setWait(ciwait.getQty());

            //小计
            zucompany.setSubtotal(zucompany.getOne().add(zucompany.getTwo()).add(zucompany.getThree()).add(zucompany.getFour()).add(zucompany.getWait()));
            cicompany.setSubtotal(cicompany.getOne().add(cicompany.getTwo()).add(cicompany.getThree()).add(cicompany.getFour()).add(cicompany.getWait()));

            //合计
            BigDecimal total = zucompany.getSubtotal().add(cicompany.getSubtotal());
            zucompany.setTotal(total);
            cicompany.setTotal(total);

            //设备完好率
            if (total.compareTo(BigDecimal.ZERO) == 0) {
                zucompany.setRatio(BigDecimal.ZERO);
                cicompany.setRatio(BigDecimal.ZERO);
            } else {
                //                BigDecimal divide = (zucompany.getOne().add(zucompany.getTwo()).add(cicompany.getOne()).add(cicompany.getTwo())).divide(total, 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal divide = (zucompany.getOne().add(zucompany.getTwo()).add(cicompany.getOne()).add(cicompany.getTwo())).divide(total, 4, BigDecimal.ROUND_HALF_UP);
                zucompany.setRatio(divide);
                cicompany.setRatio(divide);
            }

            result.add(zucompany);
            result.add(cicompany);
        }


        //        if (CollUtil.isNotEmpty(result)) {
        //            RatringComparisonVo zu = new RatringComparisonVo("总计", true);
        //            RatringComparisonVo ci = new RatringComparisonVo("总计", false);
        //
        //            zu.setOne(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getOne).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            zu.setTwo(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getTwo).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            zu.setThree(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getThree).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            zu.setFour(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getFour).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            zu.setWait(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getWait).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            zu.setSubtotal(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getSubtotal).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //
        //            ci.setOne(result.stream().filter(c -> !c.getIscore()).map(RatringComparisonVo::getOne).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            ci.setTwo(result.stream().filter(c -> !c.getIscore()).map(RatringComparisonVo::getTwo).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            ci.setThree(result.stream().filter(c -> !c.getIscore()).map(RatringComparisonVo::getThree).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            ci.setFour(result.stream().filter(c -> !c.getIscore()).map(RatringComparisonVo::getFour).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            ci.setWait(result.stream().filter(c -> !c.getIscore()).map(RatringComparisonVo::getWait).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            ci.setSubtotal(result.stream().filter(c -> !c.getIscore()).map(RatringComparisonVo::getSubtotal).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //
        //            //合计
        //            zu.setTotal(result.stream().filter(RatringComparisonVo::getIscore).map(RatringComparisonVo::getTotal).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //            ci.setTotal(zu.getTotal());
        //
        //            if (zu.getTotal().compareTo(BigDecimal.ZERO) == 0) {
        //                zu.setRatio(BigDecimal.ZERO);
        //                ci.setRatio(BigDecimal.ZERO);
        //            } else {
        //                BigDecimal divide = (zu.getOne().add(zu.getTwo()).add(ci.getOne()).add(ci.getTwo())).divide(zu.getTotal(), 2, BigDecimal.ROUND_HALF_UP);
        //                zu.setRatio(divide);
        //                ci.setRatio(divide);
        //            }
        //
        //            result.add(zu);
        //            result.add(ci);
        //        }

        return result;
    }

    /**
     * 本次评级等级统计
     *
     * @param factory
     * @param orderId 评级单id
     * @param grade   选中等级
     * @param iscore  是否主要设备
     * @return
     */
    @TaskAnnotation("nowRatingGradeCount")
    public List<RatingGradeCensusVo> nowRatingGradeCount(SessionFactory factory, String companyId, String orderId, Integer grade, Boolean iscore) {

        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        // 获取评级单位在 单元数的id
        RatingUnitBean deptNode = factory.getMapper(RatingUnitMapper.class).queryByEquipmentId(companyId);
        // 符合条件的设备
        List<RatingUnitHistoryBean> ratingUnitHistoryBeans = mapper.queryByOrderIdAndNowGradeAndIscoreAndFullPathCodeLike(orderId, grade, iscore, deptNode.getId());

        if (CollUtil.isEmpty(ratingUnitHistoryBeans)) {
            return new ArrayList<>();
        }

        // 上次评级单
        String berforOrderId = getberforOrderId(orderId);

        if (StrUtil.isNotBlank(berforOrderId)) {
            // 部门有上次评级
            // 所有上次评级设备部件等级map
            Map<String, Integer> berforRatingGrademap = getBerforRatingGrade(mapper, berforOrderId);

            List<RatingGradeCensusVo> volist = ratingUnitHistoryBeans.stream().map(new Function<RatingUnitHistoryBean, RatingGradeCensusVo>() {
                @Override
                public RatingGradeCensusVo apply(RatingUnitHistoryBean historyBean) {
                    RatingGradeCensusVo bean = new RatingGradeCensusVo();
                    bean.setGradeRemarks(historyBean.getGradeRemarks());
                    bean.setName(historyBean.getName());
                    bean.setBeforGrade(berforRatingGrademap.get(historyBean.getEquipmentId()));
                    return bean;
                }
            }).collect(Collectors.toList());
            return volist;
        } else {
            // 部门没有上次评级
            List<RatingGradeCensusVo> volist = ratingUnitHistoryBeans.stream().map(new Function<RatingUnitHistoryBean, RatingGradeCensusVo>() {
                @Override
                public RatingGradeCensusVo apply(RatingUnitHistoryBean historyBean) {
                    RatingGradeCensusVo bean = new RatingGradeCensusVo();
                    bean.setGradeRemarks(historyBean.getGradeRemarks());
                    bean.setName(historyBean.getName());
                    return bean;
                }
            }).collect(Collectors.toList());
            return volist;
        }
    }

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    /**
     * 找上次评级单id
     *
     * @param oderId
     * @return
     */
    public String getberforOrderId(String oderId) {
        String orderId = ADOConnection.runTask(getCurrDs(), factory -> {
            RatingOrderMapper mapper = factory.getMapper(RatingOrderMapper.class);
            RatingOrderBean bean = mapper.selectByPrimaryKey(oderId);
            List<RatingOrderBean> beforlist = mapper.queryByRatingTimeBefore(new Date(), bean.getDeptId(), oderId);
            if (StringUtils.isNotEmpty(beforlist)) {
                return beforlist.stream().findFirst().get().getId();
            }
            return "";
        }, String.class);
        return orderId;
    }

    @TaskAnnotation("staEquipCount")
    public Map staEquipCount(SessionFactory factory, String orderId, List<String> equipmentIds) {
        Map<String, Integer> resultMap = new HashMap<>();
        Integer equipments = 0;
        Integer parts = 0;

        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);

        List<RatingUnitHistoryBean> unitHistoryBeanList = mapper.queryByOrderIdAndInDeptId(orderId, equipmentIds);

        if (CollectionUtil.isEmpty(unitHistoryBeanList)) {
            resultMap.put("equipments", equipments);
            resultMap.put("parts", parts);
            return resultMap;
        }
        String datasource = unitHistoryBeanList.stream().map(RatingUnitHistoryBean::getDataSources).collect(Collectors.toList()).get(0);

        equipments = mapper.selectStaCount(orderId, datasource, "5");
        parts = mapper.selectStaCount(orderId, datasource, "6");
        resultMap.put("equipments", equipments);
        resultMap.put("parts", parts);
        return resultMap;
    }

    @Deprecated
    //@TaskAnnotation("staCount")
    public Map staCount(SessionFactory factory, String orderId, List<String> deptIds) {
        Map<String, Integer> resultMap = new HashMap<>();
        Integer equipments = 0;
        Integer parts = 0;

        RatingUnitHistoryMapper mapper = factory.getMapper(RatingUnitHistoryMapper.class);
        List<RatingUnitHistoryBean> unitHistoryBeanList = mapper.queryByOrderIdAndInDeptId(orderId, deptIds);
        if (CollectionUtil.isEmpty(unitHistoryBeanList)) {
            resultMap.put("equipments", equipments);
            resultMap.put("parts", parts);
            return resultMap;
        }
        List<String> parentIds = unitHistoryBeanList.stream().map(RatingUnitHistoryBean::getDataSources).collect(Collectors.toList());

        // 单元级
        List<String> dataSources = mapper.selectByOrderIdAndDeptId(orderId, parentIds, "4");

        if (CollectionUtil.isNotEmpty(dataSources)) {
            // 设备级
            List<String> equipDataSources = mapper.selectByOrderIdAndDeptId(orderId, dataSources, "5");
            // 部件级
            List<String> partDataSources = mapper.selectByOrderIdAndDeptId(orderId, equipDataSources, "6");
            equipments = equipDataSources.size();
            parts = partDataSources.size();
        }
        resultMap.put("equipments", equipments);
        resultMap.put("parts", parts);
        return resultMap;
    }


}
